// Inspired by KF5 KColorCombo, published under LGPLv2

#include "colorcombobox.h"

#include <QAbstractItemDelegate>
#include <QApplication>
#include <QStylePainter>

class ColorComboDelegate : public QAbstractItemDelegate
{
public:
    enum
    {
        ColorRole = Qt::UserRole + 1
    };

    enum LayoutMetrics
    {
        FrameMargin = 3
    };

    explicit ColorComboDelegate(QObject *parent = 0):
        QAbstractItemDelegate(parent)
    {

    }

    virtual ~ColorComboDelegate()
    {

    }

    virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        // highlight selected item
        QStyleOptionViewItem opt(option);
        opt.showDecorationSelected = true;
        QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
        style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
        QRect innerrect = option.rect.adjusted(FrameMargin, FrameMargin, -FrameMargin, -FrameMargin);

        // inner color
        painter->setPen(Qt::transparent);
        painter->setBrush(index.data(ColorRole).value<QColor>());
        painter->setRenderHint(QPainter::Antialiasing);
        painter->drawRoundedRect(innerrect, 2, 2);
    }

    virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        Q_UNUSED(index)

        // the width does not matter, as the view will always use the maximum width available
        return QSize(100, option.fontMetrics.height() + 2 * FrameMargin);
    }
};

ColorComboBox::ColorComboBox(QWidget *parent):
    QComboBox(parent)
{
    setItemDelegate(new ColorComboDelegate(this));

    connect(this, QOverload<int>::of(&QComboBox::activated),
            this, &ColorComboBox::onActivated);
    connect(this, QOverload<int>::of(&QComboBox::highlighted),
            this, &ColorComboBox::onHighlighted);
    connect(this, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &ColorComboBox::onCurrentIndexChanged);
}

ColorComboBox::~ColorComboBox()
{

}

void ColorComboBox::setCurrentColor(const QColor &col)
{
    setCurrentIndex(m_colorList.indexOf(col));
}

QColor ColorComboBox::currentColor() const
{
    return m_colorList.value(currentIndex());
}

void ColorComboBox::setColors(const QList<QColor> &colors)
{
    clear();
    m_colorList = colors;
    for (int i=0; i<m_colorList.count(); i++)
    {
        addItem(QString());
        setItemData(i, m_colorList.value(i), ColorComboDelegate::ColorRole);
    }
}

QList<QColor> ColorComboBox::colors() const
{
    return m_colorList;
}

void ColorComboBox::onActivated(int index)
{
    emit activated(m_colorList.value(index));
}

void ColorComboBox::onHighlighted(int index)
{
    m_paintedColor = m_colorList.value(index);
    emit highlighted(m_paintedColor);
}

void ColorComboBox::onCurrentIndexChanged(int index)
{
    m_paintedColor = m_colorList.value(index);
    emit currentColorChanged(m_paintedColor);
}

void ColorComboBox::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)

    QStylePainter painter(this);
    painter.setPen(palette().color(QPalette::Text));

    QStyleOptionComboBox opt;
    initStyleOption(&opt);
    painter.drawComplexControl(QStyle::CC_ComboBox, opt);

    QRect frame = style()->subControlRect(QStyle::CC_ComboBox, &opt,
                                          QStyle::SC_ComboBoxEditField, this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::transparent);
    painter.setBrush(QBrush(m_paintedColor));
    painter.drawRoundedRect(frame.adjusted(1, 1, -1, -1), 2, 2);
}
